/*
* 请求相关的方法
* */
//引入配置对象
const {appID, appsecret} = require('../config');
//引入发送http请求的库
const rp = require('request-promise-native');
//引入menu模块（自定义菜单）
const menu = require('./menu')
//引入 api 模块
const api = require('../utils/api')
//引入工具函数
const {writeFileAsync,readFileAsync} = require('../utils/tooL')

class Wechat {
    /*
    * 获取 access-token 接口凭证
    * access_token是公众号的全局唯一接口调用凭据，公众号调用各接口时都需使用access_token
    * */

    //请求access-token
    getAccessToken() {
        //定义请求地址
        const url = `${api.accessToken}&appid=${appID}&secret=${appsecret}`;
        /*所以异步操作都应该包装一层 promise 对象，让这个也不操作执行完毕之后，再去执行后面的代码*/
        return new Promise((resolve, reject) => {
            rp({method: 'GET', json: true, url}).then(res => {
                //重新赋值凭据的过期时间：当前时间+(7200-5分钟)*1000
                res.expires_in = Date.now() + (res.expires_in - 300) * 1000;
                console.log('res')
                resolve(res);
            })
        }).catch(err => {
            reject('getAccessToken方法出了问题：' + err);
        })
    }

    //读取access-token
    readAccessToken() {
        return readFileAsync('access_token.txt')
    }

    //保存access-token
    saveAccessToken(data) {
        return writeFileAsync(data,'access_token.txt')
    }

    // access-token 是否过期
    isValidAccessToken(data) {
        // 判断是否过期
        if (!data || !data.access_token || !data.expires_in) return false
        //保存的时间大于当前的时间没有过期否则过期了
        return data.expires_in > Date.now();
    }

    //access_token 判断方法
    fentchAccessToken() {
        if (this.access_token && this.expires_in && this.isValidAccessToken(this)) {
            console.log('获取access-token')
            return Promise.resolve({
                access_token: this.access_token,
                expires_in: this.expires_in
            })
        }
        return this.readAccessToken().then(async res => {
            // 判断凭据是否过期
            if (this.isValidAccessToken(res)) {
                // 没有过期,直接使用
                return Promise.resolve(res);
            } else {
                //重新发送请求获取凭据
                const data = await this.getAccessToken()
                //保存下来
                await this.saveAccessToken(data);
                //返回请求的凭据
                return Promise.resolve(data);
            }
        }).catch(async err => {
            console.log(err)
            //重新发送请求获取凭据
            const data = await this.getAccessToken()
            //保存下来
            await this.saveAccessToken(data);
            //返回请求的凭据
            return Promise.resolve(data);
        }).then(res => {
            console.log(res)
            //将其请求回来的凭据和过期时间挂载到this上
            this.access_token = res.access_token;
            this.expires_in = res.expires_in;
            //指定fetchAccessToken方法返回值
            return Promise.resolve(res);
        })
    };


    /*
    * 获取 api_ticket 临时票据
    * api_ticket 是用于调用微信卡券JS API的临时票据，有效期为7200 秒，通过access_token 来获取。
    * */
    //请求api_ticket
    getTicket() {
        /*所以异步操作都应该包装一层 promise 对象，让这个也不操作执行完毕之后，再去执行后面的代码*/
        return new Promise(async (resolve, reject) => {
            const data = await this.fentchAccessToken()
            //定义请求地址
            const url = `${api.tictet}&access_token=${data.access_token}`;
            rp({method: 'GET', json: true, url}).then(res => {
                //重新赋值凭据的过期时间：当前时间+(7200-5分钟)*1000
                resolve({
                    ticket: res.ticket,
                    expires_in: Date.now() + (res.expires_in - 300) * 1000
                });
            })
        }).catch(err => {
            reject('getTicket方法出了问题：' + err);
        })
    }

    //读取api_ticket
    readTicket() {
        return readFileAsync('ticket.txt')
    }

    //保存api_ticket
    saveTicket(data) {
        return writeFileAsync(data,'ticket.txt')
    }

    // api_ticket 是否过期
    isValidTicket(data) {
        // 判断是否过期
        if (!data || !data.ticket || !data.expires_in) return false
        //保存的时间大于当前的时间没有过期否则过期了
        return data.expires_in > Date.now();
    }

    //api_ticket 判断方法
    fetchTicket() {
        if (this.ticket && this.expires_in && this.isValidAccessToken(this)) {
            console.log('获取ticket')
            return Promise.resolve({
                ticket: this.ticket,
                expires_in: this.expires_in
            })
        }
        return this.readTicket().then(async res => {
            // 判断凭据是否过期
            if (this.isValidTicket(res)) {
                // 没有过期,直接使用
                return Promise.resolve(res);
            } else {
                //重新发送请求获取凭据
                const data = await this.getTicket()
                //保存下来
                await this.saveTicket(data);
                //返回请求的凭据
                return Promise.resolve(data);
            }
        }).catch(async err => {
            console.log(err)
            //重新发送请求获取凭据
            const data = await this.getTicket()
            //保存下来
            await this.saveTicket(data);
            //返回请求的凭据
            return Promise.resolve(data);
        }).then(res => {
            console.log(res)
            //将其请求回来的凭据和过期时间挂载到this上
            this.ticket = res.ticket;
            this.expires_in = res.expires_in;
            //指定fetchAccessToken方法返回值
            return Promise.resolve(res);
        })
    };

    // 自定义菜单 https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
    /*
    * 用来创建自定义菜单
    * */
    createMenu(menu) {
        return new Promise(async (resolve, reject) => {
            try {
                // 获取access_token;
                const data = await this.fentchAccessToken();
                const url = `${api.menu.create}access_token=${data.access_token}`;
                //发送请求
                const result = await rp({method: 'POST', url, json: true, body: menu})
                resolve(result)
            } catch (e) {
                reject('createMenu方法出了问题：' + e);
            }
        })

    }

    /*
    * 用来删除自定义菜单
    * */
    deletemenu() {
        return new Promise(async (resolve, reject) => {
            try {
                //获取access_token
                const data = await this.fentchAccessToken();
                const url = `${api.menu.delete}access_token=${data.access_token}`
                const result = await rp({method: 'GET', url, json: true})
                resolve(result)
            } catch (e) {
                reject('deletemenu方法出了问题：' + e);
            }
        })
    }
};
//创建自定义菜单之前需要先删除自定义菜单
// (async () => {
//     const w = new Wechat()
//     let result = await w.deletemenu()
//     console.log(result)
//     result = await w.createMenu(menu)
//     console.log(result)
// })()

module.exports = Wechat;